#include "programwnd.h"
#include <QtGui>
#include "wndmanager.h"
#include "programtabledelegate.h"
#include "programtableitem.h"
#include "touchdialog.h"
#include "syscontroller.h"

//------------------------------------------------------------------------------
// PUBLIC INTERFACES
//------------------------------------------------------------------------------

ProgramWnd::ProgramWnd(QWidget *parent)
	: QWidget(parent),
	  delegate_(new ProgramTableDelegate),
	  sys_(SysController::instance())
{
	ui.setupUi(this);

	QStringList itemProperties;
//	itemProperties << "Item" << "Bias" << "Time" << "Meas" << "Filter" << "Limit" << "Judge";
	itemProperties << "ITEM" << "BRNG" << "BVAL" << "TIME" << "MRNG" 
				   << "MLOW" << "MUPP" << "FILT" << "LMIT" << "JDGE";

	ui.itemsTable->setRowCount(kItemRowCount);
	ui.itemsTable->setColumnCount(25);	// should get from define.h? TODO:
	ui.itemsTable->setVerticalHeaderLabels(itemProperties);
	
	int validHeight = ui.itemsTable->height()
					- ui.itemsTable->horizontalHeader()->height() - 20;
	for(int r = 0; r < ui.itemsTable->rowCount(); ++r){
		ui.itemsTable->setRowHeight(r, validHeight / itemProperties.size());
	}

	int validWidth = ui.itemsTable->width() - 65;
//				   - ui.itemsTable->verticalHeader()->width() - 30;
	for(int c = 0; c < ui.itemsTable->columnCount(); ++c){
		ui.itemsTable->setColumnWidth(c, validWidth / 5);
	}
	ui.itemsTable->horizontalScrollBar()->setVisible(false);

	//ui.itemsTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
	ui.itemsTable->setSelectionBehavior(QAbstractItemView::SelectColumns);
	ui.itemsTable->setFont(QFont("Fixedsys", 14));
	ui.itemsTable->setItemDelegate(delegate_);

	ui.itemsCombo->addItems(sys_->ItemsList());
	ui.devicesCombo->addItems(sys_->DevicesList());

	SwitchFrame();

	connect(ui.insertButton, SIGNAL(clicked()), this, SLOT(onInsertClicked()));
	connect(ui.deleteButton, SIGNAL(clicked()), this, SLOT(onDeleteClicked()));
	connect(ui.expandButton, SIGNAL(clicked()), this, SLOT(SwitchFrame()));
	connect(ui.foldButton, SIGNAL(clicked()), this, SLOT(SwitchFrame()));
	connect(ui.devicesCombo, SIGNAL(currentIndexChanged(const QString&)), 
			this, SLOT(deviceTypeChanged(const QString&)));
	connect(delegate_, SIGNAL(itemEditingFinished(int)), 
			this, SLOT(refreshItem(int)));
	connect(ui.detailButton, SIGNAL(clicked()), this, SLOT(wndShouldReturn()));
	connect(ui.returnButton, SIGNAL(clicked()), this, SLOT(wndShouldReturn()));
	connect(ui.newButton, SIGNAL(clicked()), this, SLOT(onNewClicked()));
	connect(ui.saveButton, SIGNAL(clicked()), this, SLOT(onSaveClicked()));
	connect(ui.itemsTable, SIGNAL(cellClicked(int, int)),
			this, SLOT(onCellClicked(int, int)));

	Init();
}

ProgramWnd::~ProgramWnd()
{
	delete ui.itemsTable;
	delete ui.devicesCombo;
	delete ui.itemsCombo;
	delete ui.newButton;
	delete ui.saveButton;
	delete ui.returnButton;
	delete ui.insertButton;
	delete ui.deleteButton;
	delete ui.expandButton;
	delete ui.foldButton;
	delete ui.detailButton;
	delete ui.frame1;
	delete ui.frame2;
}

//------------------------------------------------------------------------------
// SLOTS
//------------------------------------------------------------------------------

void ProgramWnd::onCellClicked(int r, int c)
{
	QScrollBar *scroll = ui.itemsTable->horizontalScrollBar();
	scroll->setValue(c - 2);
}

void ProgramWnd::onNewClicked()
{
	sys_->NewProgram();
	Init();
}

void ProgramWnd::onSaveClicked()
{
	WndManager::gotoWnd(WndManager::kWndSaveFileWnd);
}

void ProgramWnd::wndShouldReturn()
{
	QPushButton *button = qobject_cast<QPushButton *>(sender());
	if (button == ui.detailButton) {
		int item_index = ui.itemsTable->currentColumn();
		if (sys_->IsMasterItem(item_index) || sys_->IsEsdItem(item_index)) {
			WndManager::gotoWnd(WndManager::kWndDetailWnd, item_index);
		}
	} else if (button == ui.returnButton) {
		if (sys_->IsProgramDirty()) {
			if (sys_->itemCount() <= 0) {
				WndManager::gotoWnd(WndManager::kWndMainMenu);
			} else {
				QString info = "Program not saved, are you sure to exit?";
				TouchDialog *dialog = new TouchDialog(info);
				if (dialog->exec() == QDialog::Accepted) {
					delete dialog;
					WndManager::gotoWnd(WndManager::kWndMainMenu);
				} else {
					// TODO: reload program	
					delete dialog;
				}
			}
		} else {
			WndManager::gotoWnd(WndManager::kWndMainMenu);
		}
	}
}



void ProgramWnd::onInsertClicked()
{
	InsertItem(ui.itemsTable->currentColumn());
}

void ProgramWnd::onDeleteClicked()
{
	DeleteItem(ui.itemsTable->currentColumn());
}

void ProgramWnd::deviceTypeChanged(const QString& type)
{
	sys_->setDeviceType(type);	
}

void ProgramWnd::SwitchFrame()
{
	if (ui.frame1->isVisible() && ui.frame2->isVisible()) {
		ui.frame2->setVisible(false);
	} else if (ui.frame1->isVisible()) {
		ui.frame1->setVisible(false);
		ui.frame2->setVisible(true);
	} else {
		ui.frame2->setVisible(false);
		ui.frame1->setVisible(true);
	}
}



void ProgramWnd::refreshItem(int item_index)
{
	LoadItem(item_index);
}

//------------------------------------------------------------------------------
// PRIVATE FUNCTIONS
//------------------------------------------------------------------------------


void ProgramWnd::Init()
{
	ui.devicesCombo->setCurrentIndex(
						ui.devicesCombo->findText(sys_->deviceType()));
	LoadItemsFrom(0);		
}


void ProgramWnd::LoadItem(int item_index)
{
	if (item_index >= sys_->itemCount()) {
		return;
	}
	if (IsColumnEmpty(item_index)) {
		CreateColumnWidgets(item_index);
	}
	// Item name & suffix & channel
	QTableWidgetItem *widgetItem = 
			ui.itemsTable->item(kItemRowNameSuffixCh, item_index);
	widgetItem->setText(sys_->itemNameChnSuffix(item_index));
	// bias range
	widgetItem = ui.itemsTable->item(kItemRowBiasRng, item_index);
	widgetItem->setText(sys_->itemBiasRng(item_index));
	//widgetItem->setText(sys_->itemBiasValUnit(item_index));
	// bias val
	widgetItem = ui.itemsTable->item(kItemRowBiasVal, item_index);
	widgetItem->setText(sys_->itemBiasVal(item_index));
	// wait time
	widgetItem = ui.itemsTable->item(kItemRowWaitTime, item_index);
	widgetItem->setText(sys_->itemWaitTime(item_index));
	// meas range
	widgetItem = ui.itemsTable->item(kItemRowMeasRng, item_index);
	widgetItem->setText(sys_->itemMeasRng(item_index));
	// meas lower
	widgetItem = ui.itemsTable->item(kItemRowMeasValLower, item_index);
	widgetItem->setText(sys_->itemMeasVal(item_index, true));
	// meas upper
	widgetItem = ui.itemsTable->item(kItemRowMeasValUpper, item_index);
	widgetItem->setText(sys_->itemMeasVal(item_index, false));
	// filter option
	widgetItem = ui.itemsTable->item(kItemRowFilter, item_index);
	widgetItem->setText(sys_->itemFilterOpt(item_index));
	// vol limit	
	widgetItem = ui.itemsTable->item(kItemRowVolLimit, item_index);
	widgetItem->setText(sys_->itemVolLimit(item_index));
	// limit judge
	widgetItem = ui.itemsTable->item(kItemRowLimitJudge, item_index);
	widgetItem->setText(sys_->itemLimitJudge(item_index));
}

void ProgramWnd::LoadItemsFrom(int from_index)
{
	for (int itm_idx = from_index; itm_idx < sys_->itemCount(); ++itm_idx) {
		LoadItem(itm_idx);
	}

	// clear deleted items
	for (int col = sys_->itemCount(); 
			col < ui.itemsTable->columnCount(); ++col) {
		if (!IsColumnEmpty(col)) {
			for (int row = kItemRowNameSuffixCh; row < kItemRowCount; ++row) {
				ui.itemsTable->item(row, col)->setText("");
			}
		}
	}

	// cannot change device type when there are items in the program
	ui.devicesCombo->setEnabled(sys_->itemCount() < 1);
}

int ProgramWnd::InsertItem(int item_index)
{
	int ret = sys_->InsertItem(item_index, ui.itemsCombo->currentText());
	if (0 == ret) {
		LoadItemsFrom(item_index);
	}
	return ret;
}

int ProgramWnd::DeleteItem(int item_index)
{
	int ret = sys_->RemoveItem(item_index);
	if (0 == ret) {
		LoadItemsFrom(item_index);
	}
	return ret;
}

bool ProgramWnd::IsColumnEmpty(int col) const
{
	return (ui.itemsTable->item(0, col) == NULL);
}


void ProgramWnd::CreateColumnWidgets(int col)
{
	QTableWidgetItem *widgetItem = NULL;
	for (int row = 0; row < kItemRowCount; ++row) {
	//	widgetItem = new QTableWidgetItem;
	//	widgetItem->setTextAlignment(Qt::AlignCenter);
		widgetItem = new ProgramTableItem;
		ui.itemsTable->setItem(row, col, widgetItem);
	}
}


